#include "tcpkernel.h"
#include"../select/tcpserver.h"
IKernel *TCPKernel::m_pKernel=new TCPKernel;
TCPKernel::TCPKernel() {
    m_pTCPNet=new TCPServer;

    m_pSQL=new CMySql;

    strcpy(m_szSystemPath,"E:/QTFILE/0918test/code");


}

TCPKernel::~TCPKernel()
{
    delete m_pTCPNet;
    delete m_pSQL;

}

bool TCPKernel::open(const char *szip, short nport)
{
    if(!m_pTCPNet->initNetWork(szip,nport)){
        printf("init net work err/n");
        return false;

    }
    if(!m_pSQL->ConnectMySql("localhost","root","JACKfujiled623","0907disk")){
        printf("connect mysql err\n");
        return FALSE;

    }




    return TRUE;

}

void TCPKernel::close()
{
    m_pTCPNet->unInitNetWork("");
    m_pSQL->DisConnect();

}

void TCPKernel::dealDate(SOCKET sock, const char *szbuf)
{
    switch(*szbuf){
    case _default_procotol_register_rq:
        registerrq(sock,szbuf);
        break;
    case _default_procotol_login_rq:
        loginrq(sock,szbuf);
        break;
    case _default_procotol_getfilelist_rq:
        getfilelist_rq(sock,szbuf);
        break;
    case _default_procotol_uploadfileinfo_rq:
        uploadfileinforq(sock,szbuf);
        break;
    case _default_procotol_uploadfileblock_rq:
        uploadfileblockrq(sock,szbuf);
        break;
    case _default_procotol_downloadfileinfo_rq:
        downloadfileinforq(sock, szbuf);
        break;
    case _default_procotol_downloadfileblock_rq:
        downloadfileblockrq(sock, szbuf);
        break;
    case _default_procotol_deletefile_rq:
        deletefilerq(sock, szbuf);
        break;
    case _default_procotol_searchfile_rq:
        searchfilerq(sock, szbuf);
        break;
    case _default_procotol_rename_rq:
        renameFile(sock, szbuf);
        break;
    }
}

void TCPKernel::registerrq(SOCKET sock, const char *szbuf)
{
    STRU_REGISTER_RQ*psrr=(STRU_REGISTER_RQ*)szbuf;
    //注册请求
    //1.将信息写入信息库
    list<string> lststr;
    char szsql[SQLLEN]={0};
    char szPath[MAX_PATH]={0};
    STRU_REGISTER_RS srr;
    srr.m_szResult=registerfail;

    sprintf(szsql,"insert into user(u_tel,u_name,u_password) values(%lld,'%s','%s');",psrr->m_tel,psrr->m_szName,psrr->m_szPassword);
    if(m_pSQL->UpdateMySql(szsql)){
        //1.1如果成功，创建当前用户目录
        //获取用户id
        sprintf(szsql,"select  u_id from user where u_tel=%lld;",psrr->m_tel);
        m_pSQL->SelectMySql(szsql,1,lststr);
        if(lststr.size()>0){
            string strUserId=lststr.front();
            lststr.pop_front();

            sprintf(szPath,"%s%s",m_szSystemPath,strUserId.c_str());
            CreateDirectoryA(szPath,0);
            srr.m_szResult=registersuccess;

        }
    }
    //2.回复
    m_pTCPNet->sendData(sock,(char*)&srr,sizeof(srr));
    //printf("success");
}

void TCPKernel::loginrq(SOCKET sock, const char *szbuf)
{
    STRU_LOGIN_RQ*pslr=(STRU_LOGIN_RQ*)szbuf;
    STRU_LOGIN_RS slr;

    char szsql[SQLLEN]={0};
    list<string> lststr;
    slr.m_szResult=loginusernoexist;

    sprintf(szsql,"select u_id,u_password from user where u_name='%s';",pslr->m_szName);
    m_pSQL->SelectMySql(szsql,2,lststr);

    if(lststr.size()>0){
        string strUserId=lststr.front();
        lststr.pop_front();
        string strUserPassWord=lststr.front();
        lststr.pop_front();
        slr.m_szResult=loginpassword_err;
        if(0==strcmp(strUserPassWord.c_str(),pslr->m_szPassword)){
            //
            slr.m_szResult=loginsuccess;
            slr.m_userId=atoll(strUserId.c_str());
        }
    }
    m_pTCPNet->sendData(sock,(char*)&slr,sizeof(slr));


}

void TCPKernel::getfilelist_rq(SOCKET sock, const char *szbuf)
{


        STRU_GETFILELIST_RQ* psgr = (STRU_GETFILELIST_RQ*)szbuf;
        STRU_GETFILELIST_RS sgr;
        sgr.m_userId = psgr->m_userId;
        sgr.m_pageIndex = psgr->m_pageIndex;
        sgr.m_pageSize = psgr->m_pageSize;
        sgr.m_nFileNum = 0;
        sgr.m_totalCount = 0;

        char szsql[SQLLEN] = {0};
        list<string> lststr;

        // 查询文件总数
        sprintf(szsql, "SELECT COUNT(*) FROM myview WHERE u_id=%lld;", psgr->m_userId);
        if (m_pSQL->SelectMySql(szsql, 1, lststr) && lststr.size() > 0) {
            sgr.m_totalCount = atoi(lststr.front().c_str());
            lststr.clear();
        }

        // 查询当前页的文件列表
        sprintf(szsql, "SELECT f_name, f_size, f_uploadtime FROM myview "
                       "WHERE u_id=%lld LIMIT %d OFFSET %d;",
                psgr->m_userId, psgr->m_pageSize, psgr->m_pageIndex * psgr->m_pageSize);

        m_pSQL->SelectMySql(szsql, 3, lststr);
        int i = 0;
        while (lststr.size() > 0 && i < FILENUM) {
            string strFileName = lststr.front(); lststr.pop_front();
            string strFileSize = lststr.front(); lststr.pop_front();
            string strFileUploadtime = lststr.front(); lststr.pop_front();

            strcpy(sgr.m_aryFileInfo[i].m_szFileName, strFileName.c_str());
            strcpy(sgr.m_aryFileInfo[i].m_szFileUploadTime, strFileUploadtime.c_str());
            sgr.m_aryFileInfo[i].m_filesize = atoll(strFileSize.c_str());
            i++;
        }
        sgr.m_nFileNum = i;

        // 发送响应
        m_pTCPNet->sendData(sock, (char*)&sgr, sizeof(sgr));





}

void TCPKernel::uploadfileinforq(SOCKET sock, const char *szbuf)
{
    STRU_UPLOADFILEINFO_RQ *psur = (STRU_UPLOADFILEINFO_RQ*)szbuf;
    char szsql[SQLLEN] = {0};
    list<string> lststr;
    STRU_UPLOADFILEINFO_RS sur;
    strcpy(sur.m_szFileName, psur->m_szFileName);
    strcpy(sur.m_szFileMD5, psur->m_szFileMD5);
    sur.m_filepos = psur->m_filepos; // 使用客户端提供的文件位置
    sprintf(szsql, "SELECT u_id,f_id,f_count,f_size FROM myview WHERE f_name='%s';", psur->m_szFileName);
    m_pSQL->SelectMySql(szsql, 4, lststr);

    if(lststr.size() > 0) {
        // 文件已存在
        string strUserId = lststr.front(); lststr.pop_front();
        string strFileId = lststr.front(); lststr.pop_front();
        string strFileCount = lststr.front(); lststr.pop_front();
        string strFileSize = lststr.front(); lststr.pop_front();

        long long userId = atoll(strUserId.c_str());
        long long fileId = atoll(strFileId.c_str());
        long long serverFileSize = atoll(strFileSize.c_str());
        sur.m_fileId = fileId;

        // 检查是否是续传
        if (psur->m_filepos > 0) {
            // 续传请求
            if (psur->m_filepos == serverFileSize) {
                // 文件已完整
                sur.m_szResult = uploadfileinfo_isuploaded;
            } else if (psur->m_filepos < serverFileSize) {
                // 继续上传
                sur.m_szResult = uploadfileinfo_continue;
                sur.m_filepos = psur->m_filepos;
            } else {
                // 异常情况，位置超过文件大小
                sur.m_szResult = uploadfileinfo_normal;
                sur.m_filepos = 0;
            }
        } else {
            // 新上传请求
            if (serverFileSize == psur->m_filesize) {
                sur.m_szResult = uploadfileinfo_isuploaded;
            } else {
                sur.m_szResult = uploadfileinfo_normal;
            }
        }

        // 如果是自己传的且文件不完整
        if (userId == psur->m_userId && serverFileSize < psur->m_filesize) {
            sur.m_szResult = uploadfileinfo_continue;
            sur.m_filepos = serverFileSize;
        }
    } else {
        // 新文件
        sur.m_szResult = uploadfileinfo_normal;
        sur.m_filepos = 0;

        char szFilePath[260] = {0};
        sprintf(szFilePath, "%s%lld/%s", m_szSystemPath, psur->m_userId, psur->m_szFileName);

        // 创建目录（如果不存在）
        char szDirPath[260] = {0};
        sprintf(szDirPath, "%s%lld", m_szSystemPath, psur->m_userId);
        CreateDirectoryA(szDirPath, NULL);

        // 写入数据库
        sprintf(szsql, "INSERT INTO file(f_name,f_size,f_uploadtime,f_path,f_MD5) VALUES('%s',%lld,'%s','%s','%s');",
                psur->m_szFileName, psur->m_filesize, psur->m_szFileUploadTime, szFilePath, psur->m_szFileMD5);
        m_pSQL->UpdateMySql(szsql);

        // 获取文件ID
        sprintf(szsql, "SELECT f_id FROM file WHERE f_MD5='%s'", psur->m_szFileMD5);
        m_pSQL->SelectMySql(szsql, 1, lststr);

        if(lststr.size() > 0) {
            string strFileId = lststr.front();
            sur.m_fileId = atoll(strFileId.c_str());

            // 关联用户和文件
            sprintf(szsql, "INSERT INTO user_file(u_id,f_id) VALUES(%lld,%lld);", psur->m_userId, sur.m_fileId);
            m_pSQL->UpdateMySql(szsql);
        }
    }

    m_pTCPNet->sendData(sock, (char*)&sur, sizeof(sur));
    // STRU_UPLOADFILEINFO_RQ *psur = (STRU_UPLOADFILEINFO_RQ*)szbuf;
    // // 判断服务器是否存在这个文件
    // char szsql[SQLLEN] = {0};
    // list<string> lststr;
    // STRU_UPLOADFILEINFO_RS sur;
    // strcpy(sur.m_szFileName, psur->m_szFileName);
    // strcpy(sur.m_szFileMD5, psur->m_szFileMD5);
    // sur.m_filepos = 0;

    // // 增加f_path字段查询
    // sprintf(szsql, "select u_id,f_id,f_count,f_size,f_path from myview where f_name='%s';", psur->m_szFileName);
    // m_pSQL->SelectMySql(szsql, 5, lststr);  // 查询字段数改为5
    // if(lststr.size() > 0) {
    //     // 如果存在
    //     string strUserId = lststr.front(); lststr.pop_front();
    //     string strFileId = lststr.front(); lststr.pop_front();
    //     string strFileCount = lststr.front(); lststr.pop_front();
    //     string strFileSize = lststr.front(); lststr.pop_front();
    //     string strFilePath = lststr.front(); lststr.pop_front();  // 获取文件路径

    //     long long serverFileSize = atoll(strFileSize.c_str());
    //     long long userId = atoll(strUserId.c_str());
    //     long long fileId = atoll(strFileId.c_str());
    //     sur.m_fileId = fileId;

    //     // 重构文件完整性验证逻辑
    //     bool bFileComplete = false;
    //     long long actualFileSize = -1;  // 实际文件大小（未知状态为-1）

    //     //使用 _stat 结构体和 _stat 函数
    //     struct _stat fileStat;
    //     if (_stat(strFilePath.c_str(), &fileStat) == 0) {
    //         // 使用 _stat 函数
    //         actualFileSize = fileStat.st_size;
    //         //相等为true
    //         bFileComplete = (actualFileSize == psur->m_filesize);
    //     } else {

    //         // 文件不存在但数据库有记录，使用数据库记录
    //         bFileComplete = (serverFileSize == psur->m_filesize);
    //         actualFileSize = 0;
    //     }

    //     // 根据文件完整性和用户关系处理不同情况
    //     if(bFileComplete) {
    //         // 文件已完整存在
    //         if(userId == psur->m_userId) {
    //             sur.m_szResult = uploadfileinfo_isuploaded;  // 自己已上传过
    //         } else {
    //             sur.m_szResult = uploadfileinfo_flash;       // 秒传
    //             // 增加引用计数
    //             sprintf(szsql, "update file set f_count=f_count+1 where f_id =%lld;", fileId);
    //             m_pSQL->UpdateMySql(szsql);
    //             // 添加用户文件关联
    //             sprintf(szsql, "insert into user_file(u_id,f_id) values(%lld,%lld);", psur->m_userId, fileId);
    //             m_pSQL->UpdateMySql(szsql);
    //         }
    //     } else {
    //         // 文件不完整 - 断点续传
    //         sur.m_szResult = uploadfileinfo_continue;

    //         //优先使用实际文件大小作为续传位置
    //         long long resumePos = (actualFileSize >= 0) ? actualFileSize : serverFileSize;
    //         sur.m_filepos = resumePos;

    //         // 更新任务列表中的文件位置
    //         bool bFoundInList = false;
    //         auto ite = m_lstFileINfo.begin();
    //         while(ite != m_lstFileINfo.end()) {
    //             if(fileId == (*ite)->m_fileId) {
    //                 (*ite)->m_pos = resumePos;
    //                 bFoundInList = true;
    //                 break;
    //             }
    //             ite++;
    //         }

    //         //如果任务列表中不存在，创建新任务
    //         if(!bFoundInList) {
    //             // 以追加模式打开文件
    //             FILE* pfile = fopen(strFilePath.c_str(), "ab+");
    //             if(pfile) {
    //                 fseek(pfile, resumePos, SEEK_SET);  // 定位到续传位置

    //                 STRU_FILEINFO* p = new STRU_FILEINFO;
    //                 p->m_filesize = psur->m_filesize;
    //                 p->m_fileId = fileId;
    //                 p->m_pfile = pfile;
    //                 p->m_pos = resumePos;
    //                 p->m_userId = userId;
    //                 strcpy(p->m_szFileMD5, psur->m_szFileMD5);
    //                 m_lstFileINfo.push_back(p);

    //                 // 更新数据库记录以匹配实际文件大小
    //                 if (actualFileSize >= 0 && actualFileSize != serverFileSize) {
    //                     sprintf(szsql, "update file set f_size=%lld where f_id=%lld;",
    //                             actualFileSize, fileId);
    //                     m_pSQL->UpdateMySql(szsql);
    //                 }
    //             }
    //         }
    //     }
    // }
    // else {
    //     // 如果不存在 - 全新上传
    //     sur.m_szResult = uploadfileinfo_normal;

    //     char szFilePath[260] = {0};
    //     sprintf(szFilePath, "%s%lld/%s", m_szSystemPath, psur->m_userId, psur->m_szFileName);

    //     //插入文件记录
    //     sprintf(szsql, "insert into file(f_name,f_size,f_uploadtime,f_path,f_MD5) "
    //                    "values('%s',%lld,'%s','%s','%s');",
    //             psur->m_szFileName, psur->m_filesize, psur->m_szFileUploadTime,
    //             szFilePath, psur->m_szFileMD5);
    //     if(!m_pSQL->UpdateMySql(szsql)) {
    //         // 错误处理（简单返回）
    //         return;
    //     }

    //     // 通过MD5查询文件ID
    //     lststr.clear();
    //     sprintf(szsql, "select f_id from file where f_MD5='%s'", psur->m_szFileMD5);
    //     if(!m_pSQL->SelectMySql(szsql, 1, lststr)) {
    //         // 错误处理
    //         return;
    //     }

    //     long long fileId = 0;
    //     if(lststr.size() > 0) {
    //         string strFileId = lststr.front();
    //         fileId = atoll(strFileId.c_str());
    //         sur.m_fileId = fileId;
    //     }

    //     // 插入用户文件关联
    //     sprintf(szsql, "insert into user_file(u_id,f_id) values(%lld,%lld);",
    //             psur->m_userId, fileId);
    //     if(!m_pSQL->UpdateMySql(szsql)) {
    //         // 错误处理
    //         return;
    //     }

    //     // 创建文件任务
    //     FILE* pfile = fopen(szFilePath, "wb");
    //     if(pfile) {
    //         STRU_FILEINFO* p = new STRU_FILEINFO;
    //         p->m_filesize = psur->m_filesize;
    //         p->m_fileId = fileId;
    //         p->m_pfile = pfile;
    //         p->m_pos = 0;
    //         p->m_userId = psur->m_userId;
    //         strcpy(p->m_szFileMD5, psur->m_szFileMD5);
    //         m_lstFileINfo.push_back(p);
    //     }
    // }

    // // 发送响应给客户端
    // m_pTCPNet->sendData(sock, (char*)&sur, sizeof(sur));

}

void TCPKernel::uploadfileblockrq(SOCKET sock, const char *szbuf)
{
    STRU_UPLOADFILEBLOCK_RQ* psur = (STRU_UPLOADFILEBLOCK_RQ*)szbuf;

    // 获取文件路径
    char szsql[SQLLEN] = {0};
    list<string> lststr;
    sprintf(szsql, "SELECT f_path FROM file WHERE f_id=%lld;", psur->m_fileId);
    m_pSQL->SelectMySql(szsql, 1, lststr);

    if(lststr.empty()) {
        // 文件不存在，发送失败响应
        STRU_UPLOADFILEBLOCK_RS sur;
        sur.m_fileId = psur->m_fileId;
        sur.m_blockResult = 0;
        m_pTCPNet->sendData(sock, (char*)&sur, sizeof(sur));
        return;
    }

    string filePath = lststr.front();
    FILE* pFile = fopen(filePath.c_str(), "ab"); // 以追加模式打开

    if(!pFile) {
        // 无法打开文件，发送失败响应
        STRU_UPLOADFILEBLOCK_RS sur;
        sur.m_fileId = psur->m_fileId;
        sur.m_blockResult = 0;
        m_pTCPNet->sendData(sock, (char*)&sur, sizeof(sur));
        return;
    }

    // 写入文件
    size_t written = fwrite(psur->m_szFileContent, 1, psur->m_fileblocksize, pFile);
    fclose(pFile);

    // 发送响应
    STRU_UPLOADFILEBLOCK_RS sur;
    sur.m_fileId = psur->m_fileId;
    sur.m_blockResult = (written == psur->m_fileblocksize) ? 1 : 0;
    m_pTCPNet->sendData(sock, (char*)&sur, sizeof(sur));

    // 更新文件大小
    if(written > 0) {
        sprintf(szsql, "UPDATE file SET f_size=f_size+%zu WHERE f_id=%lld;",
                written, psur->m_fileId);
        m_pSQL->UpdateMySql(szsql);
    }
//     STRU_UPLOADFILEBLOCK_RQ*psur=(STRU_UPLOADFILEBLOCK_RQ*)szbuf;
//     STRU_FILEINFO*p=NULL;
//     auto ite =m_lstFileINfo.begin();
//     while(ite!=m_lstFileINfo.end()){
//         if(psur->m_fileId==(*ite)->m_fileId){
//             p=*ite;
//             break;
//         }
//         ite++;
//     }

//     if(p && p->m_pfile) {
//         // 定位文件指针到当前位置
//         if (ftell(p->m_pfile) != p->m_pos) {
//             fseek(p->m_pfile, p->m_pos, SEEK_SET);
//         }

//     size_t nWriteNum=fwrite(psur->m_szFileContent,sizeof(char),psur->m_fileblocksize,p->m_pfile);

//         // 强制刷新缓冲区
//         fflush(p->m_pfile);

//     if(nWriteNum>0){
//         // 更新服务器端位置
//         p->m_pos+=nWriteNum;
//         if(p->m_pos==p->m_filesize){
//             fclose(p->m_pfile);
//             delete p;
//             m_lstFileINfo.erase(ite);
//         }



//     }


// }
}
void TCPKernel::downloadfileinforq(SOCKET sock, const char *szbuf)
{
    // 1. 解析客户端请求，接收到的数据缓冲区强制转换为相应的结构体指针

    STRU_DOWNLOADFILEINFO_RQ *psdr = (STRU_DOWNLOADFILEINFO_RQ*)szbuf;
    STRU_DOWNLOADFILEINFO_RS sdr;
    strcpy(sdr.m_szFileName, psdr->m_szFileName);
    sdr.m_nResult = downloadfileinfo_file_not_exist; // 默认文件不存在

    char szsql[SQLLEN] = {0};
    list<string> lststr;

    // 查询文件信息
    sprintf(szsql, "SELECT f_id, f_size, f_MD5 FROM file WHERE f_name='%s' AND f_id IN (SELECT f_id FROM user_file WHERE u_id=%lld);",
            psdr->m_szFileName, psdr->m_userId);

    if (m_pSQL->SelectMySql(szsql, 3, lststr)) {
        if (lststr.size() > 0) {
            string strFileId = lststr.front(); lststr.pop_front();
            string strFileSize = lststr.front(); lststr.pop_front();
            string strFileMD5 = lststr.front(); lststr.pop_front();

            sdr.m_fileId = atoll(strFileId.c_str());
            sdr.m_filesize = atoll(strFileSize.c_str());
            strcpy(sdr.m_szFileMD5, strFileMD5.c_str());
            sdr.m_nResult = downloadfileinfo_file_exist; // 文件存在
        }
    }

    // 发送回复
    m_pTCPNet->sendData(sock, (char*)&sdr, sizeof(sdr));
}

void TCPKernel::downloadfileblockrq(SOCKET sock, const char *szbuf)
{
    STRU_DOWNLOADFILEBLOCK_RQ *psdr = (STRU_DOWNLOADFILEBLOCK_RQ*)szbuf;
    STRU_DOWNLOADFILEBLOCK_RS sdr;
    sdr.m_fileId = psdr->m_fileId;
    sdr.m_pos = psdr->m_pos;
    sdr.m_blockSize = 0;  // 默认读取0字节
    // 1. 查询文件路径
    char szsql[SQLLEN] = {0};
    list<string> lststr;
    sprintf(szsql, "SELECT f_path FROM file WHERE f_id=%lld;", psdr->m_fileId);
    if (!m_pSQL->SelectMySql(szsql, 1, lststr) || lststr.empty()) {
        qDebug() << "Error: File ID" << psdr->m_fileId << "not found in database!";
        m_pTCPNet->sendData(sock, (char*)&sdr, sizeof(sdr));  // 发送空块表示失败
        return;
    }
    // 2. 打开文件
    string strFilePath = lststr.front();
    FILE *pFile = fopen(strFilePath.c_str(), "rb");
    if (!pFile) {
        qDebug() << "Error: Failed to open file" << strFilePath.c_str() << "for reading!";
        m_pTCPNet->sendData(sock, (char*)&sdr, sizeof(sdr));
        return;
    }
    // 3. 获取文件大小并验证位置有效性
    fseek(pFile, 0, SEEK_END);
    long nFileSize = ftell(pFile);  // 获取文件总大小
    rewind(pFile);  // 重置文件指针到开头
    // 检查请求位置是否超出文件范围
    if (psdr->m_pos > nFileSize) {
        qDebug() << "Error: Request position" << psdr->m_pos
                 << "exceeds file size" << nFileSize;
        fclose(pFile);
        m_pTCPNet->sendData(sock, (char*)&sdr, sizeof(sdr));
        return;
    }
    // 4. 定位到请求位置
    if (fseek(pFile, psdr->m_pos, SEEK_SET) != 0) {
        qDebug() << "Error: fseek failed for pos" << psdr->m_pos;
        fclose(pFile);
        m_pTCPNet->sendData(sock, (char*)&sdr, sizeof(sdr));
        return;
    }
    // 5. 计算安全读取大小并读取数据块
    size_t nRemaining = nFileSize - psdr->m_pos;  // 剩余字节数
    size_t nMaxRead = sizeof(sdr.m_szFileContent); // 缓冲区最大容量
    size_t nToRead = (nRemaining < nMaxRead) ? nRemaining : nMaxRead;

    if (nToRead > 0) {
        sdr.m_blockSize = fread(sdr.m_szFileContent, 1, nToRead, pFile);
        if (ferror(pFile)) {
            qDebug() << "Error: fread failed at pos" << psdr->m_pos;
            sdr.m_blockSize = 0;
        }
    } else {
        // 文件结束位置，读取0字节
        sdr.m_blockSize = 0;
    }
    fclose(pFile);

    // 6. 调试日志（实际部署时可关闭）
    qDebug() << "Sending block: FileID=" << psdr->m_fileId
             << "Pos=" << psdr->m_pos
             << "Size=" << sdr.m_blockSize
             << "TotalSize=" << nFileSize;

    // 7. 发送数据块
    if (m_pTCPNet->sendData(sock, (char*)&sdr, sizeof(sdr)) <= 0) {
        qDebug() << "Error: Failed to send block data!";
    }

    // STRU_DOWNLOADFILEBLOCK_RQ *psdr = (STRU_DOWNLOADFILEBLOCK_RQ*)szbuf;
    // STRU_DOWNLOADFILEBLOCK_RS sdr;
    // sdr.m_fileId = psdr->m_fileId;
    // sdr.m_pos = psdr->m_pos;
    // sdr.m_blockSize = 0; // 默认读取0字节

    // // 根据文件ID获取文件路径
    // char szsql[SQLLEN] = {0};
    // list<string> lststr;
    // sprintf(szsql, "SELECT f_path FROM file WHERE f_id=%lld;", psdr->m_fileId);

    // if (m_pSQL->SelectMySql(szsql, 1, lststr) && lststr.size() > 0) {
    //     string strFilePath = lststr.front();
    //     FILE *pFile = fopen(strFilePath.c_str(), "rb");
    //     if (pFile) {
    //         // 定位到请求的位置
    //         fseek(pFile, psdr->m_pos, SEEK_SET);
    //         // 读取文件内容
    //         sdr.m_blockSize = fread(sdr.m_szFileContent, 1, sizeof(sdr.m_szFileContent), pFile);
    //         fclose(pFile);
    //     }
    // }

    // // 发送文件块数据
    // m_pTCPNet->sendData(sock, (char*)&sdr, sizeof(sdr));
}

void TCPKernel::deletefilerq(SOCKET sock, const char *szbuf)
{//获取客户端发送的请求
    STRU_DELETEFILE_RQ *psdr = (STRU_DELETEFILE_RQ*)szbuf;
    STRU_DELETEFILE_RS sdr;
    strcpy(sdr.m_szFileName, psdr->m_szFileName);
    sdr.m_nResult = deletefile_fail; // 默认失败

    char szsql[SQLLEN] = {0};//sql语句
    list<string> lststr;//sql查询结果

    // 1. 检查文件是否存在且属于该用户
    sprintf(szsql, "SELECT user_file.f_id FROM user_file "
                   "JOIN file ON user_file.f_id = file.f_id "
                   "WHERE user_file.u_id = %lld AND file.f_name = '%s'",
            psdr->m_userId, psdr->m_szFileName);

    if (m_pSQL->SelectMySql(szsql, 1, lststr) && lststr.size() > 0) {
        string strFileId = lststr.front();
        long long fileId = atoll(strFileId.c_str());

        // 2. 删除用户文件关联
        sprintf(szsql, "DELETE FROM user_file WHERE u_id = %lld AND f_id = %lld",
                psdr->m_userId, fileId);

        if (m_pSQL->UpdateMySql(szsql)) {
            // 3. 检查文件引用计数
            sprintf(szsql, "SELECT f_count FROM file WHERE f_id = %lld", fileId);
            lststr.clear();
            if (m_pSQL->SelectMySql(szsql, 1, lststr) && lststr.size() > 0) {
                int refCount = atoi(lststr.front().c_str());

                if (refCount == 1) {
                    // 4. 如果是最后一个引用，删除物理文件和数据库记录
                    //查询文件地址
                    sprintf(szsql, "SELECT f_path FROM file WHERE f_id = %lld", fileId);
                    lststr.clear();
                    if (m_pSQL->SelectMySql(szsql, 1, lststr) && lststr.size() > 0) {
                        string filePath = lststr.front();
                        // 删除物理文件
                        remove(filePath.c_str());
                    }

                    // 删除文件记录
                    sprintf(szsql, "DELETE FROM file WHERE f_id = %lld", fileId);
                    m_pSQL->UpdateMySql(szsql);
                } else {
                    // 5. 减少引用计数
                    sprintf(szsql, "UPDATE file SET f_count = f_count - 1 WHERE f_id = %lld", fileId);
                    m_pSQL->UpdateMySql(szsql);
                }

                sdr.m_nResult = deletefile_success;
            }
        }
    } else {
        sdr.m_nResult = deletefile_not_exist;
    }

    // 发送响应
    m_pTCPNet->sendData(sock, (char*)&sdr, sizeof(sdr));
}

//？？？？？？？？？？？？？？？
void TCPKernel::searchfilerq(SOCKET sock, const char *szbuf)
{
    STRU_SEARCHFILE_RQ *psr = (STRU_SEARCHFILE_RQ*)szbuf;
    STRU_SEARCHFILE_RS ssr;
    ssr.m_userId = psr->m_userId;
    ssr.m_pageIndex = psr->m_pageIndex;
    ssr.m_pageSize = psr->m_pageSize;
    ssr.m_totalCount = 0;
    ssr.m_nFileNum = 0;
    char szsql[SQLLEN] = {0};
    list<string> lststr;
    // 构建搜索条件
    QString condition;
    switch (psr->m_searchType) {
    case SEARCH_BY_NAME:
        // 精确文件名匹配
        sprintf(szsql, "f_name = '%s'", psr->m_searchKey);
        condition = szsql;
        break;
    case SEARCH_BY_PARTIAL:
        // 部分文件名匹配
        sprintf(szsql, "f_name LIKE '%%%s%%'", psr->m_searchKey);
        condition = szsql;
        break;
    case SEARCH_BY_TIME:
        // 时间范围匹配
        sprintf(szsql, "f_uploadtime BETWEEN '%s' AND '%s'",
                psr->m_startTime, psr->m_endTime);
        condition = szsql;
        break;
    }
    // 查询总记录数
    sprintf(szsql, "SELECT COUNT(*) FROM myview WHERE u_id=%lld AND %s;",
            psr->m_userId, condition.toStdString().c_str());
    if (m_pSQL->SelectMySql(szsql, 1, lststr) && lststr.size() > 0) {
        ssr.m_totalCount = atoi(lststr.front().c_str());
        lststr.clear();
    }

    // 查询当前页的数据
    sprintf(szsql, "SELECT f_name, f_size, f_uploadtime FROM myview "
                   "WHERE u_id=%lld AND %s "
                   "LIMIT %d OFFSET %d;",
            psr->m_userId, condition.toStdString().c_str(),
            psr->m_pageSize, psr->m_pageIndex * psr->m_pageSize);

    if (m_pSQL->SelectMySql(szsql, 3, lststr)) {
        int i = 0;
        while (lststr.size() >= 3 && i < FILENUM) {
            string strFileName = lststr.front(); lststr.pop_front();
            string strFileSize = lststr.front(); lststr.pop_front();
            string strFileUploadTime = lststr.front(); lststr.pop_front();

            strcpy(ssr.m_aryFileInfo[i].m_szFileName, strFileName.c_str());
            ssr.m_aryFileInfo[i].m_filesize = atoll(strFileSize.c_str());
            strcpy(ssr.m_aryFileInfo[i].m_szFileUploadTime, strFileUploadTime.c_str());
            i++;
        }
        ssr.m_nFileNum = i;
    }

    // 发送搜索结果
    m_pTCPNet->sendData(sock, (char*)&ssr, sizeof(ssr));
}

void TCPKernel::renameFile(SOCKET sock, const char *szbuf)
{
        STRU_RENAME_RQ* prr = (STRU_RENAME_RQ*)szbuf;
        STRU_RENAME_RS rs;
        strcpy(rs.m_szOldFileName, prr->m_szOldFileName);
        strcpy(rs.m_szNewFileName, prr->m_szNewFileName);
        rs.m_nResult = 0; // 默认失败
        char szsql[SQLLEN] = {0};
        list<string> lststr;

        // 1. 检查原文件是否存在且属于该用户
        sprintf(szsql, "SELECT user_file.f_id, file.f_path FROM user_file "
                       "JOIN file ON user_file.f_id = file.f_id "
                       "WHERE user_file.u_id = %lld AND file.f_name = '%s'",
                prr->m_userId, prr->m_szOldFileName);

        if (m_pSQL->SelectMySql(szsql, 2, lststr) && lststr.size() == 2) {
            string strFileId = lststr.front();
            lststr.pop_front();
            string strFilePath = lststr.front();
            long long fileId = atoll(strFileId.c_str());

            QString filePath = QString::fromStdString(strFilePath);
            QFileInfo fileInfo(filePath);
            // 检查原文件是否存在
            if (!QFile::exists(filePath)) {
                qDebug() << "原文件不存在:" << filePath;
                rs.m_nResult = 2; // 文件不存在
                m_pTCPNet->sendData(sock, (char*)&rs, sizeof(rs));
                return;
            }
            // 2. 检查新文件名是否已存在
            sprintf(szsql, "SELECT COUNT(*) FROM file "
                           "JOIN user_file ON file.f_id = user_file.f_id "
                           "WHERE user_file.u_id = %lld AND file.f_name = '%s'",
                    prr->m_userId, prr->m_szNewFileName);
            lststr.clear();
            if (m_pSQL->SelectMySql(szsql, 1, lststr) && lststr.size() > 0) {
                int count = atoi(lststr.front().c_str());
                if (count == 0) {
                    // 构建新路径
                    QDir dir = fileInfo.dir();
                    QString newPath = dir.filePath(prr->m_szNewFileName);
                    qDebug() << "尝试重命名:" << filePath << "->" << newPath;
                    // 3. 重命名物理文件
                    if (QFile::rename(filePath, newPath)) {
                        // 4. 更新数据库中的文件名和路径
                        QString escapedPath = newPath;
                        escapedPath.replace("'", "''");
                        sprintf(szsql, "UPDATE file SET f_name = '%s', f_path = '%s' WHERE f_id = %lld",
                                prr->m_szNewFileName, escapedPath.toStdString().c_str(), fileId);

                        if (m_pSQL->UpdateMySql(szsql)) {
                            rs.m_nResult = 1; // 成功
                            qDebug() << "重命名成功";
                        } else {
                            // 数据库更新失败，尝试恢复文件名
                            QFile::rename(newPath, filePath);
                            rs.m_nResult = 0; // 失败
                            qDebug() << "数据库更新失败";
                        }
                    } else {
                        rs.m_nResult = 0; // 失败
                        qDebug() << "文件重命名失败";
                    }
                } else {
                    rs.m_nResult = 3; // 新文件名已存在
                    qDebug() << "新文件名已存在";
                }
            }
        } else {
            rs.m_nResult = 2; // 文件不存在
            qDebug() << "数据库查询不到文件";
        }

        // 发送响应
        m_pTCPNet->sendData(sock, (char*)&rs, sizeof(rs));
    }



